--[[
	是一个service，专门处理离线角色的数据（role数据不在内存中，没有agent）
	用户其实有三态，
	1，完全离线，offline，在这个service里面处理，直接读写datanode（redis，mysql）
	2，在线，在agent中，是logining成功状态（修改datanode，内存）
	3，在线，在agent中，但是（非登录）登录中，或者退出状态（todo：插入 harverst表，等再登录到主界面后去点击收割）
]]

local filename = "offlinerole.lua"

local skynet = require "skynet"
local cluster = require "skynet.cluster"
require "skynet.manager"
local queue = require "skynet.queue"

local filelog = require "filelog"
local configdao = require "configdao"
local timetool = require "timetool"
local tabletool = require "tabletool"

local dbstruct = require "dbstruct"
local routerbase = require "routerbase"
require "pubenum"

local json = require "cjson"
json.encode_sparse_array(true,1,1)

local Offline = routerbase:new()
local cs = queue()

function Offline.CMD.change_prop(rid, itemvalues, comment)
	local prop_id = tonumber(itemvalues.prop_id)
    local value = tonumber(itemvalues.value)

    if not prop_id or not prop_id then
        return false
    end

    --获得道具配置
    local curitem = skynet.call(".knapsack", "lua", "getpropconf", prop_id)
    if not curitem then
        return false
    end

    local updateitem = { id = prop_id}
    local kid = math.floor(prop_id / 100)
    if kid == PropKind.HEADFRAME then   --头像框,增加有效时间
        updateitem.value = value * curitem.effecttime * 24 * 3600
    elseif kid == PropKind.INTERPROP or kid == PropKind.VIPCARD then    --会员卡 互动表情，增加数量
        updateitem.value = value
    else
        return false
    end

    --更新
    skynet.send(".knapsack", "lua", "updateknapsack", rid, {[1] = updateitem})

    return true
end

function Offline.CMD.charge_prop(rid, prop_id, value, comment)
    local result = Offline.CMD.change_prop(rid, {prop_id = prop_id, value = value}, comment)
    if result then
        local logstr = string.format("%d,%d,%d,%d,%s", EGateAction.CHARGEPROP, rid, prop_id or 0, value or 0, comment.table_tradeid)
	    skynet.send(".gamedatalog", "lua", "write", logstr)
    else
        filelog.sys_error("charge prop error!",rid, prop_id, value, comment)
        return false
    end

    return true
end

function Offline.CMD.reduce_prop(rid, prop_id, value)
	if value >= 0 then
        filelog.sys_error("error, value <= 0 !",rid, prop_id, value)
	    return false
	end

    local result = Offline.CMD.change_prop(rid, {prop_id = prop_id, value = value})
    if not result then
        filelog.sys_error("reduce prop error!",rid, prop_id, value)
        return false
    end
	
    return true
end

function Offline.CMD.change_money(rid, itemvalues, comment)
	-- todo：这里应该是直接修改db, 还是插入harverst表
	-- 这里只是方便暂时做一些测试
	local status, result
	result = cluster.call("datanode", ".router", "select_rk", rid, "rs_money", true)
	if result[1] == 0 then
		return false --调试开发阶段，暂时不检查是否新记录
	end
	local rolemoney = tabletool.deepcopy(result[2][rid])
	local setargs = {}
	for item, value in pairs(itemvalues) do
		if item ~= "coin" and item ~= "diamond" and item ~= "fangka" then
            filelog.sys_error("value type error!",rid, item, itemvalues, comment)
			return false
		end
		-- 数据修改有有问题，退出，这个请求都不生效
		if (rolemoney[item] + value) < 0  then
			value = 0 - rolemoney[item]
			filelog.sys_error("------------ offline change_money error:sum<0", rid, rolemoney, itemvalues, comment)
		end

		setargs[item] = rolemoney[item] + value
	end

	status, result = skynet.pcall(cluster.call, "datanode", ".router", "update_rk", rid, "rs_money", 0, setargs)
	if (status == true and result[1] == 1 and result[2] == true) then
		return setargs
	else
		-- todo :怎么打错误日志，而且这块是比较严重的，涉及到数据回滚的问题
        filelog.sys_error("update database data failed!",rid, itemvalues, comment)
		return false
	end
end

local function real_change_diamond(rid, bv, value, ev, comment)
	local status, result
	result = cluster.call("datanode", ".router", "select_rk", rid, "rs_money", true)
	if result[1] == 0 then
		return false --调试开发阶段，暂时不检查是否新记录
	end
	local rolemoney = tabletool.deepcopy(result[2][rid])
	local setargs = {}
	-- 如果有bv参数，则检查一下bv参数是否等于数据源的最初值，如果没有，只是记录日志
	if bv and rolemoney["diamond"] ~= bv then
		-- 记录报警日志
	end

	-- 数据修改有有问题，退出，这个请求都不生效
	if (rolemoney["diamond"] + value) < 0  then
		-- 记录日志
		return false
	end
	setargs["diamond"] = rolemoney["diamond"] + value
	local bd = rolemoney["diamond"] or 0 -- begin diamond
	local ed = setargs["diamond"]  or 0-- end diamond
	local ld = rolemoney["lock_diamond"] or 0 -- lock_diamond

	status, result = skynet.pcall(cluster.call, "datanode", ".router", "update_rk", rid, "rs_money", 0, setargs)
	if (status == true and result[1] == 1 and result[2] == true) then
		return setargs, {bd=bd, ed=ed, ld=ld}
	else
		-- todo :怎么打错误日志，而且这块是比较严重的，涉及到数据回滚的问题
		return false
	end
end

local function change_diamond(rid, bv, value, ev, comment)
	return cs(real_change_diamond, rid, bv, value, ev, comment)
end

local function real_change_coin(rid, bv, value, ev, comment)
	local status, result
	result = cluster.call("datanode", ".router", "select_rk", rid, "rs_money", true)
	if result[1] == 0 then
		return false --调试开发阶段，暂时不检查是否新记录
	end
	local rolemoney = tabletool.deepcopy(result[2][rid])
	local setargs = {}
	-- 如果有bv参数，则检查一下bv参数是否等于数据源的最初值，如果没有，只是记录日志
	if bv and rolemoney["coin"] ~= bv then
		-- 记录报警日志
	end

	-- 数据修改有有问题，退出，这个请求都不生效
	if (rolemoney["coin"] + value) < 0  then
		-- 记录日志
		return false
	end
	setargs["coin"] = rolemoney["coin"] + value
	local bd = rolemoney["coin"] or 0 -- begin coin
	local ed = setargs["coin"]  or 0-- end coin
    local ld = rolemoney["lock_coin"] or 0 -- lock_coin

	status, result = skynet.pcall(cluster.call, "datanode", ".router", "update_rk", rid, "rs_money", 0, setargs)
	if (status == true and result[1] == 1 and result[2] == true) then
		return setargs, {bd=bd, ed=ed, ld=ld}
	else
		-- todo :怎么打错误日志，而且这块是比较严重的，涉及到数据回滚的问题
		return false
	end
end

local function change_coin(rid, bv, value, ev, comment)
	return cs(real_change_coin, rid, bv, value, ev, comment)
end

-- 直接充值金豆，所以不知道期初，期末值
function Offline.CMD.charge_diamond(rid, value, comment)
	-- addon 是为返回专门打日志用的
	local setargs, addon= change_diamond(rid, nil, value, nil, comment)
	if not setargs then
		filelog.error("offline:charge_diamond erro", rid, value, comment)
		return setargs
	end
	-- 记录日志, 这里的comment 需要到时细化
    local level = 0
    local status, result = skynet.pcall(cluster.call, "datanode", ".router", "select_rk", rid, "rs_info", true)
	if (status and result and result[1] ~= 0 and result[2]) then
        level = tonumber(result[2][rid].level) or 0
    end
	if not comment then comment = {} end
    local logstr = nil
    if tonumber(comment.agencylevel) == 1 then
        logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s", EDiamondChange.AGENCY_CHARGE, rid, level, value, 0, 0, addon.bd, addon.ed, addon.ld, comment.xxx, comment.tradeid)
    else
	    logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s", comment.change_type or EDiamondChange.OFF_CHARGE, rid, level, value, 0, 0, addon.bd, addon.ed, addon.ld, comment.xxx, comment.tradeid)
    end
	skynet.send(".diamondlog", "lua", "write", logstr)
	return setargs
end

-- 直接充值房卡
function Offline.CMD.charge_fangka(rid, value, comment)
	return Offline.CMD.change_money(rid, {fangka=value}, comment)
end

-- 下面三个是游戏过程中发来的改变，前两个钻石,后一个房卡
-- 这里的vs是一个结构 {beginvalue: value: endvalue}, 其中value是正，但这里要减去
function Offline.CMD.game_sub_fuwufei(rid, vs, rid_values, comment, nodename)
    return Offline.CMD.game_sub_diamond(rid, vs, rid_values, comment, nodename)
end

-- 下面三个是游戏过程中发来的改变，前两个钻石,后一个房卡
-- 这里的vs是一个结构 {beginvalue: value: endvalue}, 其中value是正，但这里要减去
function Offline.CMD.game_sub_diamond(rid, vs, rid_values, comment, nodename)
	local setargs, addon = change_diamond(rid, vs.beginvalue, 0-vs.value, vs.endvalue, comment)
	if not setargs then
		filelog.error("offline:sub_diamond erro", rid, vs, rid_values, comment)
		return setargs
	end

    local level = 0
    local status, result = skynet.pcall(cluster.call, "datanode", ".router", "select_rk", rid, "rs_info", true)
	if (status and result and result[1] ~= 0 and result[2]) then
        level = tonumber(result[2][rid].level) or 0
    end

    local logstr = nil
    if comment.is_fangfei then
        logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s", EDiamondChange.FANGFEI, rid, level, 0-vs.value, vs.beginvalue, vs.endvalue, addon.bd, addon.ed, addon.ld, comment.table_uuid, comment.start_time, comment.table_tradeid)
    elseif nodename == "wzq" then
	    logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s", EDiamondChange.OFF_WZQFUWUFEI, rid, level, 0-vs.value, vs.beginvalue, vs.endvalue, addon.bd, addon.ed, addon.ld, comment.table_uuid, comment.start_time, comment.table_tradeid)
	elseif nodename == "xq" then
	    logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s", EDiamondChange.OFF_XQFUWUFEI, rid, level, 0-vs.value, vs.beginvalue, vs.endvalue, addon.bd, addon.ed, addon.ld, comment.table_uuid, comment.start_time, comment.table_tradeid)
	else
        logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s", EDiamondChange.OFF_WZQFUWUFEI, rid, level, 0-vs.value, vs.beginvalue, vs.endvalue, addon.bd, addon.ed, addon.ld, comment.table_uuid, comment.start_time, comment.table_tradeid)
    end
    skynet.send(".diamondlog", "lua", "write_file_redis", logstr, rid)

	return setargs
end

-- 这里的vs是一个结构 {beginvalue: value: endvalue: rolename}, 其中value有正负
-- 中途离开扣费： had_half，如果存在这个， 说明已经结算过了， 这里只记录战绩
function Offline.CMD.game_balance_diamond(rid, vs, rid_values, comment, nodename, is_cointable)
    --机器人不结算,只是针对游戏内机器人
    if vs.level == 99 then
        return true
    end
    
	if vs.had_half == nil then
		local setargs, addon = change_diamond(rid, vs.beginvalue, vs.value, vs.endvalue, comment)
		if not setargs then
			filelog.error("offline:balance_diamond erro", rid, vs, rid_values, comment)
			return setargs
		end

        local level = 0
        local status, result = skynet.pcall(cluster.call, "datanode", ".router", "select_rk", rid, "rs_info", true)
	    if (status and result and result[1] ~= 0 and result[2]) then
            level = tonumber(result[2][rid].level) or 0
        end

		local logstr 
		if nodename == "wzq" then
			logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s", EDiamondChange.OFF_WUZIQI,  rid, level, vs.value, vs.beginvalue, vs.endvalue, addon.bd, addon.ed, addon.ld, comment.table_uuid, comment.start_time, comment.table_tradeid)
		elseif nodename == "xq" then
			logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s", EDiamondChange.OFF_XIANGQI,  rid, level, vs.value, vs.beginvalue, vs.endvalue, addon.bd, addon.ed, addon.ld, comment.table_uuid, comment.start_time, comment.table_tradeid)
		else
			logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s", EDiamondChange.OFF_BALANCE, rid, level, vs.value, vs.beginvalue, vs.endvalue, addon.bd, addon.ed, addon.ld, comment.table_uuid, comment.start_time, comment.table_tradeid)
		end
		skynet.send(".diamondlog", "lua", "write", logstr)
	end

	-- 记录钻石战绩
    if not is_cointable then
        skynet.send('.gameresult', 'lua', 'diamond_result', rid, rid_values, comment)
    end

	return 0
end

function Offline.CMD.game_half_diamond(rid, vs, rid_values, comment)
	local setargs, addon = change_diamond(rid, vs.beginvalue, vs.value, vs.endvalue, comment)
	if not setargs then
		filelog.error("offline:half_diamond erro", rid, vs, rid_values, comment)
		return setargs
	end

    local level = 0
    local status, result = skynet.pcall(cluster.call, "datanode", ".router", "select_rk", rid, "rs_info", true)
	if (status and result and result[1] ~= 0 and result[2]) then
        level = tonumber(result[2][rid].level) or 0
    end

	local logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s", EDiamondChange.OFF_HALF, rid, level, vs.value, vs.beginvalue, vs.endvalue, addon.bd, addon.ed, addon.ld, comment.table_uuid, comment.start_time, comment.table_tradeid)
	skynet.send(".diamondlog", "lua", "write", logstr)
	return 0
end

-- 下面三个是游戏过程中发来的改变，前两个钻石,后一个房卡
-- 这里的vs是一个结构 {beginvalue: value: endvalue}, 其中value是正，但这里要减去
function Offline.CMD.game_sub_coin(rid, vs, rid_values, comment, nodename)
	local setargs, addon = change_coin(rid, vs.beginvalue, 0-vs.value, vs.endvalue, comment)
	if not setargs then
		filelog.error("offline:sub_coin erro", rid, vs, rid_values, comment)
		return setargs
	end

    local level = 0
    local status, result = skynet.pcall(cluster.call, "datanode", ".router", "select_rk", rid, "rs_info", true)
	if (status and result and result[1] ~= 0 and result[2]) then
        level = tonumber(result[2][rid].level) or 0
    end

    local logstr = nil
    if nodename == "wzq" then
	    logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s", ECoinChange.OFF_WZQFUWUFEI, rid, level, 0-vs.value, vs.beginvalue, vs.endvalue, addon.bd, addon.ed, addon.ld, comment.table_uuid, comment.start_time, comment.table_tradeid)
	elseif nodename == "xq" then
	    logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s", ECoinChange.OFF_XQFUWUFEI, rid, level, 0-vs.value, vs.beginvalue, vs.endvalue, addon.bd, addon.ed, addon.ld, comment.table_uuid, comment.start_time, comment.table_tradeid)
	else
        logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s", ECoinChange.OFF_FUWUFEI, rid, level, 0-vs.value, vs.beginvalue, vs.endvalue, addon.bd, addon.ed, addon.ld, comment.table_uuid, comment.start_time, comment.table_tradeid)
    end
    skynet.send(".coinlog", "lua", "write", logstr)

	return setargs
end

-- 这里的vs是一个结构 {beginvalue: value: endvalue: rolename}, 其中value有正负
-- 中途离开扣费： had_half，如果存在这个， 说明已经结算过了， 这里只记录战绩
function Offline.CMD.game_balance_coin(rid, vs, rid_values, comment, nodename)
	if vs.had_half == nil then
		local setargs, addon = change_coin(rid, vs.beginvalue, vs.value, vs.endvalue, comment)
		if not setargs then
			filelog.error("offline:game_balance_coin erro", rid, vs, rid_values, comment)
			return setargs
		end

        local level = 0
        local status, result = skynet.pcall(cluster.call, "datanode", ".router", "select_rk", rid, "rs_info", true)
	    if (status and result and result[1] ~= 0 and result[2]) then
            level = tonumber(result[2][rid].level) or 0
        end

        local logstr = nil
        if nodename == "wzq" then
            logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s", ECoinChange.OFF_WUZIQI, rid, level, vs.value, vs.beginvalue, vs.endvalue, addon.bd, addon.ed, addon.ld, comment.table_uuid, comment.start_time, comment.table_tradeid)
        elseif nodename == "xq" then
            logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s", ECoinChange.OFF_XIANGQI, rid, level, vs.value, vs.beginvalue, vs.endvalue, addon.bd, addon.ed, addon.ld, comment.table_uuid, comment.start_time, comment.table_tradeid)
        else
		    logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s", ECoinChange.OFF_BALANCE, rid, level, vs.value, vs.beginvalue, vs.endvalue, addon.bd, addon.ed, addon.ld, comment.table_uuid, comment.start_time, comment.table_tradeid)
        end
		skynet.send(".coinlog", "lua", "write", logstr)
	end

    --记录金币战绩
    skynet.send('.gameresult', 'lua', 'coin_result', rid, rid_values, comment)
	
	return 0
end

function Offline.CMD.game_half_coin(rid, vs, rid_values, comment)
	local setargs, addon = change_coin(rid, vs.beginvalue, vs.value, vs.endvalue, comment)
	if not setargs then
		filelog.error("offline:half_coin erro", rid, vs, rid_values, comment)
		return setargs
	end

    local level = 0
    local status, result = skynet.pcall(cluster.call, "datanode", ".router", "select_rk", rid, "rs_info", true)
	if (status and result and result[1] ~= 0 and result[2]) then
        level = tonumber(result[2][rid].level) or 0
    end

	local logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s", ECoinChange.OFF_HALF, rid, level, vs.value, vs.beginvalue, vs.endvalue, addon.bd, addon.ed, addon.ld, comment.table_uuid, comment.start_time, comment.table_tradeid)
	skynet.send(".coinlog", "lua", "write", logstr)

	return 0
end

-- 房卡扣除就相对不那么讲究，直接调用 change_money()扣除就可以了
function Offline.CMD.game_sub_fangka(rid, vs, rid_values, comment)
	return Offline.CMD.change_money(rid, {coin = 0-vs.value}, comment)
end

function Offline.CMD.game_balance_fangka(rid, vs, rid_values, comment)
	skynet.send('.gameresult', 'lua', 'fangka_result', rid, rid_values, comment)
 	return true
end

function Offline.CMD.updateroleinfo(rid, itemvalues)
    itemvalues = itemvalues or {}

    local otherinfos = {}
    for k,v in pairs(itemvalues) do
        if k ~= "rid" then
            if k == "alipay_realname" or k == "bankcard_realname" 
            or k == "weixin_realname" or k == "bankcard_bankname" then
                otherinfos[k] = v
                itemvalues[k] = nil
            end
        end
    end
    
    if next(itemvalues) ~= nil then
	    cluster.call("datanode", ".router", "update_rk", rid, "rs_info", 0, itemvalues)
    end
    if next(otherinfos) ~= nil then
	    cluster.call("datanode", ".router", "update_rk", rid, "rs_otherinfo", 0, otherinfos)
    end
	return true
end

-- TODO: 在agent的非登录状态，有收获的话，插入到离线收获表中，再次登录后，进入主界面提示领取
-- change_money，是否也要通过 harvest来操作呢？
function Offline.CMD.harvest(rid, itemvalues, comment)
end

--开奖
function Offline.CMD.open_jackpot_coin(rid, vs, rid_values, comment)
	local setargs, addon = change_coin(rid, nil, vs.value, nil, comment)
    if not setargs then
		filelog.error("offline:open_jackpot_coin erro", rid, vs, rid_values, comment)
		return setargs
	end

    local level = 0
    local status, result = skynet.pcall(cluster.call, "datanode", ".router", "select_rk", rid, "rs_info", true)
	if (status and result and result[1] ~= 0 and result[2]) then
        level = tonumber(result[2][rid].level) or 0
    end
	
	local logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s", ECoinChange.OFF_JACKPOT, rid, level, vs.value, 0, 0, addon.bd, addon.ed, addon.ld, comment.table_uuid, comment.start_time, comment.table_tradeid)
	skynet.send(".coinlog", "lua", "write", logstr)
	
    return setargs
end

--开奖
function Offline.CMD.open_jackpot_diamond(rid, vs, rid_values, comment)
	local setargs, addon = change_diamond(rid, nil, vs.value, nil, comment)
    if not setargs then
		filelog.error("offline:open_jackpot_diamond erro", rid, vs, rid_values, comment)
		return setargs
	end
	
    local level = 0
    local status, result = skynet.pcall(cluster.call, "datanode", ".router", "select_rk", rid, "rs_info", true)
	if (status and result and result[1] ~= 0 and result[2]) then
        level = tonumber(result[2][rid].level) or 0
    end

	local logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s", EDiamondChange.OFF_JACKPOT, rid, level, vs.value, 0, 0, addon.bd, addon.ed, addon.ld, comment.table_uuid, comment.start_time, comment.table_tradeid)
	skynet.send(".diamondlog", "lua", "write_player_jackpot_redis", logstr, rid)
	
    return setargs
end

--奖池抽水
function Offline.CMD.jackpot_sub_diamond(rid, vs, rid_values, comment, nodename)
	local setargs, addon = change_diamond(rid, vs.beginvalue, 0-vs.value, vs.endvalue, comment)
	if not setargs then
		filelog.error("offline:jackpot_sub_diamond erro", rid, vs, rid_values, comment)
		return setargs
	end

    local level = 0
    local status, result = skynet.pcall(cluster.call, "datanode", ".router", "select_rk", rid, "rs_info", true)
	if (status and result and result[1] ~= 0 and result[2]) then
        level = tonumber(result[2][rid].level) or 0
    end

    local logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s", EDiamondChange.OFF_SUBJACKPOT, rid, level, 0-vs.value, vs.beginvalue, vs.endvalue, addon.bd, addon.ed, addon.ld, comment.table_uuid, comment.start_time, comment.table_tradeid)
    skynet.send(".diamondlog", "lua", "write_player_jackpot_redis", logstr, rid)
	return setargs
end

--奖池抽水
function Offline.CMD.jackpot_sub_coin(rid, vs, rid_values, comment, nodename)
	local setargs, addon = change_coin(rid, vs.beginvalue, 0-vs.value, vs.endvalue, comment)
	if not setargs then
		filelog.error("offline:jackpot_sub_coin erro", rid, vs, rid_values, comment)
		return setargs
	end

    local level = 0
    local status, result = skynet.pcall(cluster.call, "datanode", ".router", "select_rk", rid, "rs_info", true)
	if (status and result and result[1] ~= 0 and result[2]) then
        level = tonumber(result[2][rid].level) or 0
    end

    local logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s", ECoinChange.OFF_SUBJACKPOT, rid, level, 0-vs.value, vs.beginvalue, vs.endvalue, addon.bd, addon.ed, addon.ld, comment.table_uuid, comment.start_time, comment.table_tradeid)
    skynet.send(".coinlog", "lua", "write", logstr)

	return setargs
end

--
--更新提现状态
--
function Offline.CMD.update_withdraw_state(rid, keyid, newstate, remark)
    newstate = tonumber(newstate) or 0
    keyid = tostring(keyid) or ""   --唯一id,数据库为int类型，但取出时已转换为string

    local status,result = skynet.pcall(cluster.call, "datanode", ".router", "select_rk", rid, "rm_withdraw")
	if not status or not result[2] or result[2][keyid] == nil then
        return false
    end

    --更新状态
    local update_list = {}
    local recorditem = result[2][keyid]
    local curr_state = tonumber(recorditem.current_state)
    if newstate > curr_state and curr_state <= EWithdrawState.EWITHDRAW_STATE_COMPLETE 
    and newstate <= EWithdrawState.EWITHDRAW_STATE_BACKED then
        recorditem.current_state = newstate
        update_list.current_state = recorditem.current_state
        if newstate == EWithdrawState.EWITHDRAW_STATE_IN_HANDLE then    --处理中
            recorditem.handle_time = timetool.get_time()
            update_list.handle_time = recorditem.handle_time
        elseif newstate == EWithdrawState.EWITHDRAW_STATE_COMPLETE      --已完成
        or newstate == EWithdrawState.EWITHDRAW_STATE_REFUSED           --拒绝
        or newstate == EWithdrawState.EWITHDRAW_STATE_BACKED            --退回
        or newstate == EWithdrawState.EWITHDRAW_STATE_FAILED then       --失败
            recorditem.complete_time = timetool.get_time()
            update_list.complete_time = recorditem.complete_time
            update_list.remark = remark
        end

        --提现失败，回滚
        if recorditem.current_state == EWithdrawState.EWITHDRAW_STATE_FAILED 
        or recorditem.current_state == EWithdrawState.EWITHDRAW_STATE_BACKED then
            --直接加钻石
            local service_fee = tonumber(recorditem.service_fee) or 0
            local withdraw_value = tonumber(recorditem.withdraw_value) or 0
            local addvalue = service_fee + withdraw_value
            local setargs, addon = true,{bd = 0, ed = 0, ld = 0} --change_diamond(rid, nil, addvalue, nil, {})
            if setargs then
                --记录日志
                local logstr = nil
                local comment = { }
                local now = timetool.get_time()
                comment.tradeid = keyid
                comment.table_uuid = "gatenode" .. "_" .. 0 .. "_" .. 0 .. "_" .. now
                logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s", EDiamondChange.WITHDRAW_RETURN, rid, 0, addvalue, 0, 0,
                addon.bd, addon.ed, addon.ld, comment.table_uuid, now, comment.tradeid)
                skynet.send(".diamondlog", "lua", "write", logstr)
            end

           --提现失败，邮件通知
            local content = "在 " .. os.date("%m-%d %H:%M:%S",tonumber(recorditem.create_time)) .. " 提现金币被退回。 退回原因：" .. (remark or "")
            local fields = {subject = "金币提现退回", mail_type = EMailType.EMAIL_TYPE_TXBACK, content = content, attach_json = json.encode({diamond = addvalue}) }
            skynet.send(".mailbox", "lua", "newmail", rid, fields)
            
        elseif recorditem.current_state == EWithdrawState.EWITHDRAW_STATE_COMPLETE then
            --提现成功，更新提现总金额
            --更新累积充值金额
            local result = cluster.call("datanode", ".router", "select_rk", rid, "rs_money", true)
            if result and result[1] ~= 0 then
                local rolemoney = result[2][rid]
                local total_withdraw = tonumber(rolemoney.total_withdraw) + tonumber(recorditem.withdraw_value)
                local total_servicefee = tonumber(rolemoney.total_servicefee) + tonumber(recorditem.service_fee)
                local updatelist = {total_withdraw = total_withdraw, total_servicefee = total_servicefee}
                skynet.pcall(cluster.send, "datanode", ".router", "update_rk", rid, "rs_money", 0, updatelist)
            end
         end

        --更新提现记录
	    skynet.pcall(cluster.call, "datanode", ".router", "update_rk", rid, "rm_withdraw", keyid, update_list)
        return true
    elseif newstate == EWithdrawState.EWITHDRAW_STATE_WAIT_HANDLE 
    and curr_state == EWithdrawState.EWITHDRAW_STATE_IN_HANDLE then --处理状态变成待处理状态
        update_list.handle_time = 0
        update_list.current_state = newstate
	    skynet.pcall(cluster.call, "datanode", ".router", "update_rk", rid, "rm_withdraw", keyid, update_list)
        return true
    end

    return false 
end

skynet.start(function()
	Offline:start()
end)
